#pragma once
#include<iostream>
#include<string>
#include <jsoncpp/json/json.h>

#include"common.hpp"
#include"run.hpp"
#include"../CommonComponent/Log.hpp"
#include"compile.hpp"


namespace ns_cr
{
    std::string cr_path="./temp/";
    class CR
    {
    public:
        CR()
        {}

        ~CR()
        {}

        static void RemoveFile(std::string& filename)
        {
            std::string file=ns_common::fileUtility::AddSrcSuffix(filename);
            if(ns_common::fileUtility::IsFileEsist(file)){
                unlink(file.c_str());
            }
            file=ns_common::fileUtility::AddExeSuffix(filename);
            if(ns_common::fileUtility::IsFileEsist(file)){
                unlink(file.c_str());
            }
            file=ns_common::fileUtility::AddInSuffix(filename);
            if(ns_common::fileUtility::IsFileEsist(file)){
                unlink(file.c_str());
            }
            file=ns_common::fileUtility::AddOutSuffix(filename);
            if(ns_common::fileUtility::IsFileEsist(file)){
                unlink(file.c_str());
            }
            file=ns_common::fileUtility::AddCompileErrSuffix(filename);
            if(ns_common::fileUtility::IsFileEsist(file)){
                unlink(file.c_str());
            }
            file=ns_common::fileUtility::AddRunErrSuffix(filename);
            if(ns_common::fileUtility::IsFileEsist(file)){
                unlink(file.c_str());
            }
        }

        static std::string ErrcodeDesc(int errcode)
        {
            switch(errcode)
            {
                case -1: return "编译错误";
                case -2: return "内部错误";
                case 0:return "运行成功";
                case 6:return "超出内存限制";
                case 11: return "段错误";
                case 24:return "运行超时";
                case 8: return "浮点数溢出";
                //...
                default: return "未知错误";
            }

            return "";
        }

        static void Start(std::string& in_json,std::string& out_json)
        {
            Json::Value root;
            Json::Reader reader;
            if(!reader.parse(in_json,root)){
                Log(ERROR,"parse in_json error");
                return;
            }
            std::string code=root["code"].asString();
            std::string input=root["input"].asString();
            int timelimit=root["timelimit"].asInt();
            int spacelimit=root["spacelimit"].asInt();

            std::string filename=cr_path+ns_common::fileUtility::GetUniqueFileName();
            int errcode=0;//错误码
            int ret=0;
            //创建编译所依赖的文件
            if(!ns_common::fileUtility::CreateFile(ns_common::fileUtility::AddSrcSuffix(filename))){
                Log(ERROR,"create src file error");
                errcode=-1;
                goto END;
            }
            if(!ns_common::fileUtility::CreateFile(ns_common::fileUtility::AddCompileErrSuffix(filename))){
                Log(ERROR,"create compileErr file error");
                errcode=-1;
                goto END;
            }
            if(!ns_common::fileUtility::Write(ns_common::fileUtility::AddSrcSuffix(filename),code)){
                Log(ERROR,"write to file error");
                errcode=-1;
                goto END;
            }
            //编译
            ret=ns_compile::compile::Compile(filename);
            if(-1==ret){
                errcode=-2;
                goto END;
            }
            else if(1==ret){
                errcode=-1;
                goto END;
            }
            //创建运行所依赖的文件
            if(!ns_common::fileUtility::CreateFile(ns_common::fileUtility::AddInSuffix(filename))){
                Log(ERROR,"create stdin file error");
                errcode=-1;
                goto END;
            }
            if(!ns_common::fileUtility::CreateFile(ns_common::fileUtility::AddOutSuffix(filename))){
                Log(ERROR,"create stdout file error");
                errcode=-1;
                goto END;
            }

            if(!ns_common::fileUtility::CreateFile(ns_common::fileUtility::AddRunErrSuffix(filename))){
                Log(ERROR,"create runErr file error");
                errcode=-1;
                goto END;
            }

            input+="\n";
            if(!ns_common::fileUtility::Write(ns_common::fileUtility::AddInSuffix(filename),input)){
                Log(ERROR,"write to file error");
                errcode=-1;
                goto END;
            }

            //运行
            errcode=ns_run::run::Run(filename,timelimit,spacelimit);

            END:
            Json::Value r;
            if(errcode>-2){
                std::string _stdout;
                std::string _stderr;
                if(0==errcode){
                    if(!ns_common::fileUtility::Read(ns_common::fileUtility::AddOutSuffix(filename),_stdout)){
                        Log(ERROR,"read file error\n");
                    }
                }
                else if(-1==errcode){
                    if(!ns_common::fileUtility::Read(ns_common::fileUtility::AddCompileErrSuffix(filename),_stderr)){
                        Log(ERROR,"read file error\n");
                    }
                }
                else{
                    if(!ns_common::fileUtility::Read(ns_common::fileUtility::AddRunErrSuffix(filename),_stderr)){
                        Log(ERROR,"read file error\n");
                    }
                }
                r["status"]=std::to_string(errcode).c_str();
                r["reason"]=ErrcodeDesc(errcode).c_str();
                r["stdout"]=_stdout.c_str();
                r["stderr"]=_stderr.c_str();

            }
            else{
                //发生内部错误只需要上层知道即可，不需要用户了解
                r["status"]=std::to_string(errcode).c_str();
                r["reason"]="";
                r["stdout"]="";
                r["stderr"]="";
                Log(ERROR,ErrcodeDesc(errcode).c_str());
            }
            out_json=r.toStyledString();

            //删除所有相关文件
            RemoveFile(filename);
        }
    };
}